package net.joke.base.systems;


import net.joke.base.Config;
import net.joke.base.components.ActionQueue;
import net.joke.base.components.Effect;
import net.joke.base.components.Position;
import net.joke.base.components.Stats;
import net.joke.base.components.sub.JokeAction;
import net.joke.base.components.sub.MoveTarget;
import net.joke.base.components.sub.SkillAction;
import net.joke.base.systems.sub.MovementSubsystem;

import com.artemis.ComponentMapper;
import com.artemis.Entity;
import com.artemis.EntityProcessingSystem;
import com.artemis.World;
import com.artemis.utils.Utils;

/**
 * Sistema di gestione della coda di azioni.<br>
 * Gestisce
 * @author Gianluca
 *
 */
public class ActionSystem extends EntityProcessingSystem {
	public MovementSubsystem movementSubsystem;
	

	public ActionSystem(MovementSubsystem movementSubsystem) {
		super(Position.class, ActionQueue.class); // , Stats.class);
		
		this.movementSubsystem = movementSubsystem;
	}

	private ComponentMapper<Position> positionMapper;
	private ComponentMapper<ActionQueue> actionQueueMapper;
	private ComponentMapper<Stats> statsMapper;
	private ComponentMapper<Effect> effectMapper;

	@Override
	protected void initialize() {
		super.initialize();
		positionMapper = new ComponentMapper<Position>(Position.class, world);
		actionQueueMapper = new ComponentMapper<ActionQueue>(ActionQueue.class, world); 
		statsMapper = new ComponentMapper<Stats>(Stats.class, world); 
		effectMapper = new ComponentMapper<Effect>(Effect.class, world); 
		this.movementSubsystem.initialize(world);
	}
	
	@Override
	protected void process(Entity arg0) {
		// Recupero posizione, target e stats
		ActionQueue m = actionQueueMapper.get(arg0);
		
		JokeAction action = m.currentAction;
		if (action != null) {
			if (action.actionKind == JokeAction.ACTION_MOVE) {
				Position p = positionMapper.get(arg0);
				Stats s = statsMapper.get(arg0);
				movementSubsystem.process(world, arg0, p, (MoveTarget)action, s);
				if (action.terminated()) {
					// N.B. per le Entity Skill, una volta raggiunto il bersaglio, DEVO scatenare l'effetto e rimuovere il component.
					Effect e = effectMapper.get(arg0);
					if (e != null) {
						// TODO
						if (e.kind == Effect.EFFECT_BULLET) {
							// TODO
						}
						world.deleteEntity(arg0);
						
					} else {
						m.checkTerminated();
					}
				}
			} else if (action.actionKind == JokeAction.ACTION_SKILL) {
				Stats s = statsMapper.get(arg0);
				// controllo il global cooldown
				if (s.baseStat.cooldown == 0) {
					boolean remove = true;
					// Posso sparacchiare !!!
					Position p = positionMapper.get(arg0);
					// controllo il range
					SkillAction act = (SkillAction)action;
					MoveTarget objective = act.target;
					if (getPositionOf(objective)) {
						if (Utils.doCirclesCollide(p.x, p.y, 0, objectiveX, objectiveY, act.skill.range)) { 
							objective.terminated = false;
							if (Config.effectsSpawn.spawn(arg0, p, action, world)) {
								// Se torna true, devo rimuovere l'action. Target fuori range o Morto
								remove = false;
							}
						}
					}
					if (remove) {
						m.checkTerminated();
					}
					s.baseStat.cooldown = s.actualStat.hitSpeed;
				}
			}
		}
	}	
	
	private float objectiveX;
	private float objectiveY;
	
	public boolean getPositionOf(MoveTarget objective) {
		if (objective.entityTarget != null) {
			Entity e = objective.entityTarget.get(world);
			if (e != null) {
				Position objPos = positionMapper.get(e);
				if (objPos != null) {
					objectiveX = objPos.x;
					objectiveY = objPos.y;
					return true;
				}
			}
		} else {
			objectiveX = objective.x;
			objectiveY = objective.y;
			return true;
		}
		return false;
	}
	
	
}
